package org.example.sentinel;

import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.time.Duration;

@Service
public class IpMonitorService {
    
    private final ReactiveRedisTemplate<String, String> redisTemplate;
    
    // 异常计数键前缀
    private static final String EXCEPTION_COUNT_PREFIX = "ip:exception:";
    // 黑名单键前缀
    private static final String BLACKLIST_PREFIX = "ip:blacklist:";
    
    // 异常阈值
    private static final int EXCEPTION_THRESHOLD = 10;
    // 黑名单持续时间
    private static final Duration BLACKLIST_DURATION = Duration.ofMinutes(1);
    
    public IpMonitorService(ReactiveRedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    
    /**
     * 记录IP异常
     */
    public Mono<Void> recordException(String ip) {
        String key = EXCEPTION_COUNT_PREFIX + ip;
        
        return redisTemplate.opsForValue().increment(key)
            .flatMap(count -> {
                if (count >= EXCEPTION_THRESHOLD) {
                    return addToBlacklist(ip);
                }
                return Mono.empty();
            })
            .then();
    }
    
    /**
     * 添加IP到黑名单
     */
    public Mono<Void> addToBlacklist(String ip) {
        String key = BLACKLIST_PREFIX + ip;
        
        return redisTemplate.opsForValue().set(key, "1", BLACKLIST_DURATION)
            .then(redisTemplate.delete(EXCEPTION_COUNT_PREFIX + ip))
            .then();
    }
    
    /**
     * 检查IP是否在黑名单
     */
    public Mono<Boolean> isBlacklisted(String ip) {
        return redisTemplate.hasKey(BLACKLIST_PREFIX + ip);
    }
}